Nongenetic inhertance map of systematic reviews

knitr::opts_chunk$set(echo = TRUE)

library(readxl)
library(plyr)
library(tibble)
library(dplyr)
library(tidyverse)
library(stringr)
library(knitr)
library(forcats)
library(ggplot2)
library(hrbrthemes)  #for ggplot2
library(bibliometrix)
library(igraph)

Data loading

# manually extracted data
xldata <- "./Data_extraction_postcrosschecking.xlsx"

# bibliometric data
bib <- convert2df("./bibliometric.bib", dbsource = "scopus", format = "bibtex")

Data organisation

Splitting list of tabs into separate dataframes

excel_sheets(path = xldata)
tab_names <- excel_sheets(path = xldata)


# creating a list of dataframes per tab
list_all <- lapply(tab_names, function(x) read_excel(path = xldata, sheet = x))

# assigning tab names to each dataframe
names(list_all) <- tab_names

# get dataframes out of list
list2env(list_all, .GlobalEnv)

Addressing objectives 1 and 2

  1. Map the SR literature across disciplines e.g., the types of environmental exposures and traits synthesised, the proportion of SRs that examine inter- versus trans-generational effects, and which disciplines dominate the non-genetic inheritance SR literature. The map will highlight gaps in the literature that remain to be synthesised or have very few SRs.

  2. Present discipline-specific research patterns by summarising commonalities and disparities between disciplines (e.g., do SRs of specific environmental exposures dominate one discipline and not others? Do some disciplines focus on inter-generational effects, and another on trans-generational effects?).

Percent of SR’s within disciplines

count_discipline <- Review_info %>%
    count(discipline_code) %>%
    arrange(desc(n))
percent_discipline <- count_discipline %>%
    mutate(percent = (n/sum(n)) * 100)
percent_discipline$discipline_code <- factor(percent_discipline$discipline_code,
    level = percent_discipline$discipline_code[order(percent_discipline$n, decreasing = FALSE)])

ggplot(percent_discipline, aes(x = discipline_code, y = percent)) + geom_col(aes(fill = ""),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    xlab("Discipline") + scale_fill_manual(values = c("#919191")) + theme(legend.position = "none",
    axis.title.x = element_text(size = 10))

Inter- vs trans-generational effects within and between disciplines

Merged_inter_vs_trans <- merge(Inter_vs_trans_info, Review_info)

count_inter_vs_trans <- Merged_inter_vs_trans %>%
    count(inter_vs_trans_code, by = discipline_code) %>%
    arrange(desc(n))
percent_inter_vs_trans <- count_inter_vs_trans %>%
    mutate(percent = (n/sum(n)) * 100)

percent_inter_vs_trans <- percent_inter_vs_trans %>%
    rename(discipline_code = by)

ggplot(percent_inter_vs_trans, aes(x = inter_vs_trans_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Inter_vs_trans_info_unique <- Inter_vs_trans_code_info %>%
    select(controlled_vocab_inter_vs_trans, description)
unique(Inter_vs_trans_info_unique)
## # A tibble: 3 x 2
##   controlled_vocab_inter_vs_trans description       
##   <chr>                           <chr>             
## 1 inter                           inter-generational
## 2 trans                           trans-generational
## 3 unclear                         unclear

Descendant generations within and between disciplines

merged_descendant_generat <- merge(Descendant_generat_info, Review_info)

count_descendant_generat <- merged_descendant_generat %>%
    count(descendant_generat_code, by = discipline_code) %>%
    arrange(desc(n))
percent_descendant_generat <- count_descendant_generat %>%
    mutate(percent = (n/sum(n)) * 100)

percent_descendant_generat <- percent_descendant_generat %>%
    rename(discipline_code = by)

ggplot(percent_descendant_generat, aes(x = descendant_generat_code, y = percent)) +
    geom_col(aes(fill = discipline_code), width = 0.7) + theme_light() + coord_flip() +
    scale_y_continuous(name = "Percent") + theme(legend.position = "bottom", axis.title.x = element_text(size = 10),
    axis.title.y = element_blank()) + guides(fill = guide_legend(title = "Discipline:"))

Terminology used within and between disciplines

I.e., does the use of inter- and trans-generational inheritance match our definitions (see Fig. 1)

count_terminology <- Review_info %>%
    count(terminology_code, by = discipline_code) %>%
    arrange(desc(n))
percent_terminology <- count_terminology %>%
    mutate(percent = (n/sum(n)) * 100)

percent_terminology <- percent_terminology %>%
    rename(discipline_code = by)

ggplot(percent_terminology, aes(x = terminology_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

terminology_code_unique <- Terminology_code_info %>%
    select(controlled_vocab_terminology, description_terminology)
unique(terminology_code_unique)
## # A tibble: 4 x 2
##   controlled_vocab_terminology description_terminology 
##   <chr>                        <chr>                   
## 1 yes                          yes                     
## 2 no                           no                      
## 3 not used                     does not use these terms
## 4 unclear                      unclear

Types of non-genetic transmission within and between disciplines

I.e., are the non-genetic effects conferred through the matriline or patriline etc.

Merged_transmission_info <- merge(Transmission_info, Review_info)

count_transmission <- Merged_transmission_info %>%
    count(transmission_code, by = discipline_code) %>%
    arrange(desc(n))
percent_transmission <- count_transmission %>%
    mutate(percent = (n/sum(n)) * 100)

percent_transmission <- percent_transmission %>%
    rename(discipline_code = by)

ggplot(percent_transmission, aes(x = transmission_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Transmission_info_unique <- Transmission_code_info %>%
    select(controlled_vocab_transmission, description)
unique(Transmission_info_unique)
## # A tibble: 4 x 2
##   controlled_vocab_transmi… description                                         
##   <chr>                     <chr>                                               
## 1 matriline                 matriline                                           
## 2 patriline                 patriline                                           
## 3 not separated             not separated (i.e., the primary studies used do no…
## 4 unclear                   unclear/unspecefied

F0 environmental manipulations within and between disciplines

merged_F0_env <- merge(F0_env_info, Review_info)

count_F0_env <- merged_F0_env %>%
    count(F0_env_code, by = discipline_code) %>%
    arrange(desc(n))
percent_F0_env <- count_F0_env %>%
    mutate(percent = (n/sum(n)) * 100)

percent_F0_env <- percent_F0_env %>%
    rename(discipline_code = by)

ggplot(percent_F0_env, aes(x = F0_env_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

F0_env_info_unique <- F0_env_code_info %>%
    select(controlled_vocab_F0_env, description)
unique(F0_env_info_unique)
## # A tibble: 9 x 2
##   controlled_vocab_F0_e… description                                            
##   <chr>                  <chr>                                                  
## 1 diet                   diet                                                   
## 2 human induced          human induced pollutant/toxin                          
## 3 environmental composi… natural variation in environmental composition (e.g., …
## 4 psychological stress   psychological stress (e.g., post-natal separation)     
## 5 temperature            temperature                                            
## 6 human health           ‘human health’ related environments (e.g., tobacco, al…
## 7 population demographic differences in population demographics (e.g., populati…
## 8 light                  light and/or photoperiod                               
## 9 other                  other/unclear

Environmental effect direction within and between disciplines

I.e., are the effects of environment predicted to have negative, positive, or neutral effects on offspring phenotype

merged_env_eff <- merge(Env_eff_diection_info, Review_info)

count_env_eff <- merged_env_eff %>%
    count(env_eff_direction_code, by = discipline_code) %>%
    arrange(desc(n))
percent_env_eff <- count_env_eff %>%
    mutate(percent = (n/sum(n)) * 100)

percent_env_eff <- percent_env_eff %>%
    rename(discipline_code = by)

ggplot(percent_env_eff, aes(x = env_eff_direction_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Env_eff_direction_info_unique <- Env_eff_direction_code_info %>%
    select(controlled_vocab_env_eff_direction, description)
unique(Env_eff_direction_info_unique)
## # A tibble: 3 x 2
##   controlled_vocab_env_eff_direction description
##   <chr>                              <chr>      
## 1 negative                           negative   
## 2 positive                           positive   
## 3 unclear                            unclear

F0 environmental exposure timing within and between disciplines

Note: We excluded SRs that solely focused on environmental exposures that occured when the F0 generation was a fetus (i.e., pre-natal). However, some broader SRs (i.e., eco evo SRs) included primary studies where the F0 generation was exposed pre-natally. This was therefore coded in our data.

merged_exposure_timing <- merge(Exposure_timing_info, Review_info)

count_exposure_timing <- merged_exposure_timing %>%
    count(exposure_timing_code, by = discipline_code) %>%
    arrange(desc(n))
percent_exposure_timing <- count_exposure_timing %>%
    mutate(percent = (n/sum(n)) * 100)

percent_exposure_timing <- percent_exposure_timing %>%
    rename(discipline_code = by)

ggplot(percent_exposure_timing, aes(x = exposure_timing_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used, and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Exposure_timing_info_unique <- Exposure_timing_code_info %>%
    select(controlled_vocab_exposure_timing, description)
unique(Exposure_timing_info_unique)
## # A tibble: 5 x 2
##   controlled_vocab_exposure_timing description                               
##   <chr>                            <chr>                                     
## 1 pre-natal                        pre-natally                               
## 2 post-natal                       post-natal before sexual maturity         
## 3 post-sexual maturity             after sexual maturity but before gestation
## 4 gestation                        during gestation                          
## 5 unclear                          other/unclear

Descendant traits within and between disciplines

merged_descendant_trait <- merge(Descendant_trait_info, Review_info)

count_descendant_trait <- merged_descendant_trait %>%
    count(descendant_trait_code, by = discipline_code) %>%
    arrange(desc(n))
percent_descendant_trait <- count_descendant_trait %>%
    mutate(percent = (n/sum(n)) * 100)

percent_descendant_trait <- percent_descendant_trait %>%
    rename(discipline_code = by)

ggplot(percent_descendant_trait, aes(x = descendant_trait_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Descendant_trait_info_unique <- Descendant_trait_code_info %>%
    select(controlled_vocab_descendant_trait, description)
unique(Descendant_trait_info_unique)
## # A tibble: 9 x 2
##   controlled_vocab_descendan… description                                       
##   <chr>                       <chr>                                             
## 1 physiological               physiological (e.g., immune function, insulin lev…
## 2 morphological               morphological (e.g., body size, adiposity, colour…
## 3 reproductive                reproductive (e.g., fecundity and sexual trait me…
## 4 life history                life-history (e.g., developmental rate, aging and…
## 5 survival                    descendant survival/aging (must be post-natally)  
## 6 behavioural                 behavioural (e.g., response to stimuli, anxiety, …
## 7 molecular                   molecular (e.g., gene expression, DNA methylation…
## 8 health                      health and disease (e.g., disease prevalence )    
## 9 unclear                     other/unclear

Descendant sex within and between disciplines

merged_descendant_sex <- merge(Descendant_sex_info, Review_info)

count_descendant_sex <- merged_descendant_sex %>%
    count(descendant_sex_code, by = discipline_code) %>%
    arrange(desc(n))
percent_descendant_sex <- count_descendant_sex %>%
    mutate(percent = (n/sum(n)) * 100)

percent_descendant_sex <- percent_descendant_sex %>%
    rename(discipline_code = by)

ggplot(percent_descendant_sex, aes(x = descendant_sex_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Descendant_sex_info_unique <- Descendant_sex_code_info %>%
    select(controlled_vocab_descendant_sex, description)
unique(Descendant_sex_info_unique)
## # A tibble: 3 x 2
##   controlled_vocab_descendant_sex description
##   <chr>                           <chr>      
## 1 males                           males      
## 2 females                         females    
## 3 unclear                         unclear

Descendant age within and between disciplines

Note: We excluded SRs that solely focused on fetal traits in descendants. However, some broader SRs included primary studies that mearured fetal traits. This was therefore coeded in our data.

merged_descendant_age <- merge(Descendant_age_info, Review_info)

count_descendant_age <- merged_descendant_age %>%
    count(descendant_age_code, by = discipline_code) %>%
    arrange(desc(n))
percent_descendant_age <- count_descendant_age %>%
    mutate(percent = (n/sum(n)) * 100)

percent_descendant_age <- percent_descendant_age %>%
    rename(discipline_code = by)

ggplot(percent_descendant_age, aes(x = descendant_age_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Descendant_age_info_unique <- Descendant_age_code_info %>%
    select(controlled_vocab_descendant_age, description)
unique(Descendant_age_info_unique)
## # A tibble: 5 x 2
##   controlled_vocab_descendant_… description                                     
##   <chr>                         <chr>                                           
## 1 fetal                         fetal/embryonic                                 
## 2 juvenile                      juvenile (post-embryonic/birth prior to sexual …
## 3 adult                         adult                                           
## 4 ongoing                       ongoing                                         
## 5 unclear                       other/unclear

Higher taxononmic groups within and between disciplines

Merged_higher_taxon <- merge(Higher_taxon_info, Review_info)

count_higher_taxon <- Merged_higher_taxon %>%
    count(taxon_code, by = discipline_code) %>%
    arrange(desc(n))
percent_higher_taxon <- count_higher_taxon %>%
    mutate(percent = (n/sum(n)) * 100)

percent_higher_taxon <- percent_higher_taxon %>%
    rename(discipline_code = by)

ggplot(percent_higher_taxon, aes(x = taxon_code, y = percent)) + geom_col(aes(fill = discipline_code),
    width = 0.7) + theme_light() + coord_flip() + scale_y_continuous(name = "Percent") +
    theme(legend.position = "bottom", axis.title.x = element_text(size = 10), axis.title.y = element_blank()) +
    guides(fill = guide_legend(title = "Discipline:"))

Table showing the controlled vacabularly used and a description of what the controlled vocabulary means.

Note that the description often equals controlled vocab but this is not always the case for more complicated elements.

Higher_taxon_info_unique <- Taxon_code_info %>%
    select(controlled_vocab_taxon, description)
unique(Higher_taxon_info_unique)
## # A tibble: 5 x 2
##   controlled_vocab_taxon description  
##   <chr>                  <chr>        
## 1 vertebrates            vertebrates  
## 2 invertebrates          invertebrates
## 3 plants                 plants       
## 4 other                  other        
## 5 unclear                unclear

Descendent generation vs terminology use across disciplines

Does the terminology used (i.e., inter- vs trans-generational) match our definition (based on generation, sex and taxa) within the descendant generations examined

generat_terminology <- merge(Descendant_generat_info, Review_info)

count_generat_terminology <- generat_terminology %>%
    count(descendant_generat_code, by = terminology_code) %>%
    arrange(desc(n))
percent_generat_terminology <- count_generat_terminology %>%
    mutate(percent = (n/sum(n)) * 100)

percent_generat_terminology <- percent_generat_terminology %>%
    rename(terminology_code = by)

ggplot(percent_generat_terminology, aes(x = descendant_generat_code, y = percent)) +
    geom_col(aes(fill = terminology_code), width = 0.7) + theme_light() + coord_flip() +
    scale_y_continuous(name = "Percent") + theme(legend.position = "bottom", axis.title.x = element_text(size = 10),
    axis.title.y = element_blank()) + guides(fill = guide_legend(title = "Terminology:"))

Time trend of the number of SRs per year

Publication_info %>%
    count(year) %>%
    ggplot(aes(x = year, y = n)) + geom_area(fill = "#919191", alpha = 1) + geom_line(color = "skyblue",
    size = 1) + geom_point(size = 1, color = "blue") + theme_minimal() + scale_x_continuous(name = "",
    limits = c(2005, 2020)) + scale_y_continuous(name = "Article count", limits = c(0,
    10)) + ggtitle("Publication year") + theme(plot.title = element_text(hjust = 0.5))

Adressing objective 3

  1. Conduct bibliometric analyses of co-author networks and common terminology use across and within disciplines.

The following visualisations allow us to view bibliometric patterns from data exported directly from scopus. We are able to view common keyword use, author networks, affiliations, and citation patterns.

Author, country, and citation summary plots

results1 <- biblioAnalysis(bib)  #run basic standard descriptive analysis of the dataset (data frame)
summary(results1, k = 7, pause = F, width = 130)  #produces a sequence of standard summary tables displayed in the console
plot(results1, k = 7, pause = F)

Keyword matrix plot

NetMatrix_keywords <- biblioNetwork(bib, analysis = "co-occurrences", network = "keywords", sep = ";")
NetMatrix_keywords_plot <- networkPlot(NetMatrix_keywords, normalize = "association", n = 10, Title = "Keyword co-occurrences", type = "fruchterman",
    size.cex = TRUE, size = 30, remove.multiple = F, edgesize = 10, labelsize = 3, label.cex = TRUE, edges.min = 2, cluster = "edge_betweenness")

Thematic map

map_thematic <- thematicMap(bib, field = "ID", n = 1000, minfreq = 5, stemming = FALSE, size = 0.5, n.labels = 1, repel = TRUE)
plot(map_thematic$map)

Author collaboration network

NetMatrix_authors <- biblioNetwork(bib, analysis = "collaboration", network = "authors", sep = ";")
NetMatrix_authors_plot <- networkPlot(NetMatrix_authors, n = 20, Title = "Author collaboration", type = "auto", size = 15, size.cex = TRUE,
    edgesize = 10, labelsize = 1)

Country collaboration network

bib_sco2 <- metaTagExtraction(bib, Field = "AU_CO", sep = ";")  #we need to extract countries from the affiliations first
# bib_sco2$AU_CO[1:10]
NetMatrix_country <- biblioNetwork(bib_sco2, analysis = "collaboration", network = "countries", sep = ";")
NetMatrix_country_plot <- networkPlot(NetMatrix_country, n = 50, Title = "Country collaboration", type = "auto", size = TRUE, remove.multiple = FALSE,
    labelsize = 1.5)

Addressing objective 4

  1. Conduct a critical appraisal of the SR literature to assess the rigour, transparency, and risk of bias.

The following visualisations allow us to see the average scores across each CEESAT questions as well as how each individual SR scored for each CEESAT questions. This will allow us to assess the quality and Risk of Bias of the SR literature.

Note: CEESAT questions and scoring criteria can be found in Appendix_S3 on the open Science Framework https://osf.io/detvk/.

Blinding paper ID and wrangling data into long format

Paper ID was blinded for the pilot but will not be blinded for the full study

# blinding authors
Assessment$id <- paste("ID", c(1:length(Assessment$id)), sep = "")
# shortening column names
names(Assessment) <- gsub("CEESAT_", "", names(Assessment), fixed = TRUE)
# selecting only the columns with scores selecting only the columns with scores
Assessment_reduced <- select(Assessment, c("id", !ends_with("_comment")))
# wrangling data into long format
ceesat_long <- gather(Assessment_reduced, question, score, Q1.1:Q8.1, factor_key = TRUE)

CEESAT score summary across SRs

This plot shows the average CEESAT score per question. CEESAT questions and scoring criteria can be found in Appendix_S3 on the open Science Framework https://osf.io/detvk/.

# calculating the % of scores within each questions
count_ceesat_score <- ceesat_long %>%
    count(score, by = question)
percent_ceesat_score <- count_ceesat_score %>%
    mutate(percent = (n/sum(n)) * 100)
percent_ceesat_score <- percent_ceesat_score %>%
    rename(question = by)
percent_ceesat_score$question <- as.factor(percent_ceesat_score$question)
percent_ceesat_score$question <- factor(percent_ceesat_score$question, levels(percent_ceesat_score$question)[length(percent_ceesat_score$question):1])  #reverse the order of questions
percent_ceesat_score$score <- as.factor(percent_ceesat_score$score)
percent_ceesat_score$score <- factor(percent_ceesat_score$score, levels(percent_ceesat_score$score)[c(2, 3, 1, 4)])  #set the order of levels for assessment scores:
summaryplot <- ggplot(data = percent_ceesat_score, x = question, y = percent) + geom_col(mapping = aes(x = question, y = percent, fill = score),
    width = 0.7, position = "fill", color = "black") + coord_flip(ylim = c(0, 1)) + guides(fill = guide_legend(reverse = TRUE)) + scale_fill_manual(values = c("yellow",
    "green", "orange", "red")) + theme(legend.position = "bottom", panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
    panel.background = element_blank()) + ylab("Percent") + xlab("CEESAT question") + guides(fill = guide_legend(title = "Score:"))
summaryplot

Individual CEESAT Scores

This plot shows the CEESAT score per SR. CEESAT questions and scoring criteria can be found in Appendix_S3 on the open Science Framework https://osf.io/detvk/.

scoresplot <- ggplot(data = ceesat_long, aes(y = id, x = question)) + geom_tile(color = "black", fill = "white", size = 0.8) + geom_point(aes(color = as.factor(score)),
    size = 5) + scale_x_discrete(position = "top") + guides(color = guide_legend(reverse = TRUE)) + scale_color_manual(values = c("orange",
    "yellow", "green", "red"), name = "Score:") + theme_minimal() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
    panel.background = element_blank(), legend.position = "bottom", legend.background = element_rect(linetype = "solid", colour = "grey"),
    legend.key.size = unit(0.75, "cm"), legend.text = element_text(size = 12), axis.text.y = element_text(size = 10, color = "black"),
    axis.text.x = element_text(angle = 45, hjust = 0), plot.margin = unit(c(1, 1, 1, 0), "cm")) + ylab("Study ID") + xlab("CEESAT question")
scoresplot

LS0tCnRpdGxlOiAiTm9uZ2VuZXRpYyBpbmhlcnRhbmNlIG1hcCBvZiBzeXN0ZW1hdGljIHJldmlld3MiCmF1dGhvcjogIkVyaW4gTWFjYXJ0bmV5LCBTenltZWsgRHJvYm5pYWssIFNoaW5pY2hpIE5ha2FnYXdhLCBNYWxnb3J6YXRhIExhZ2lzeiIKb3V0cHV0OiAKICAgIAogICAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgIHRvY19kZXB0aDogNAplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCiAgICAKYGBge3IsIGluY2x1ZGUgPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAptZXNzYWdlID0gRkFMU0UsCndhcm5pbmcgPSBGQUxTRSwKY2FjaGUgPSBUUlVFLCAKdGlkeSA9IFRSVUUsIAplY2hvID0gVFJVRQopCgpybShsaXN0ID0gbHMoKSkKYGBgCgoKYGBge3Igc2V0dXAsIHJlc3VsdHMgPSAnaGlkZSd9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShwbHlyKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShrbml0cikKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoaHJicnRoZW1lcykgI2ZvciBnZ3Bsb3QyCmxpYnJhcnkoYmlibGlvbWV0cml4KQpsaWJyYXJ5KGlncmFwaCkKCmBgYAojIyMgRGF0YSBsb2FkaW5nCgpgYGAge3IsIHJlc3VsdHMgPSAnaGlkZSd9CiNtYW51YWxseSBleHRyYWN0ZWQgZGF0YQp4bGRhdGEgPC0gIi4vRGF0YV9leHRyYWN0aW9uX3Bvc3Rjcm9zc2NoZWNraW5nLnhsc3giCgojYmlibGlvbWV0cmljIGRhdGEKYmliIDwtIGNvbnZlcnQyZGYoIi4vYmlibGlvbWV0cmljLmJpYiIsIGRic291cmNlID0gInNjb3B1cyIsIGZvcm1hdCA9ICJiaWJ0ZXgiKQpgYGAKCgojIyMgRGF0YSBvcmdhbmlzYXRpb24KU3BsaXR0aW5nIGxpc3Qgb2YgdGFicyBpbnRvIHNlcGFyYXRlIGRhdGFmcmFtZXMKCmBgYCB7ciwgcmVzdWx0cyA9ICdoaWRlJ30KCmV4Y2VsX3NoZWV0cyhwYXRoID0geGxkYXRhKQp0YWJfbmFtZXMgPC0gZXhjZWxfc2hlZXRzKHBhdGggPSB4bGRhdGEpCgoKI2NyZWF0aW5nIGEgbGlzdCBvZiBkYXRhZnJhbWVzIHBlciB0YWIKbGlzdF9hbGwgPC0gbGFwcGx5KHRhYl9uYW1lcywgZnVuY3Rpb24oeCkgcmVhZF9leGNlbChwYXRoID0geGxkYXRhLCBzaGVldCA9IHgpKQoKI2Fzc2lnbmluZyB0YWIgbmFtZXMgdG8gZWFjaCBkYXRhZnJhbWUKbmFtZXMobGlzdF9hbGwpIDwtIHRhYl9uYW1lcwoKI2dldCBkYXRhZnJhbWVzIG91dCBvZiBsaXN0Cmxpc3QyZW52KGxpc3RfYWxsLCAuR2xvYmFsRW52KQpgYGAKCiMjIEFkZHJlc3Npbmcgb2JqZWN0aXZlcyAxIGFuZCAyIHsudGFic2V0fQoKMSkJTWFwIHRoZSBTUiBsaXRlcmF0dXJlIGFjcm9zcyBkaXNjaXBsaW5lcyBlLmcuLCB0aGUgdHlwZXMgb2YgZW52aXJvbm1lbnRhbCBleHBvc3VyZXMgYW5kIHRyYWl0cyBzeW50aGVzaXNlZCwgdGhlIHByb3BvcnRpb24gb2YgU1JzIHRoYXQgZXhhbWluZSBpbnRlci0gdmVyc3VzIHRyYW5zLWdlbmVyYXRpb25hbCBlZmZlY3RzLCBhbmQgd2hpY2ggZGlzY2lwbGluZXMgZG9taW5hdGUgdGhlIG5vbi1nZW5ldGljIGluaGVyaXRhbmNlIFNSIGxpdGVyYXR1cmUuIFRoZSBtYXAgd2lsbCBoaWdobGlnaHQgZ2FwcyBpbiB0aGUgbGl0ZXJhdHVyZSB0aGF0IHJlbWFpbiB0byBiZSBzeW50aGVzaXNlZCBvciBoYXZlIHZlcnkgZmV3IFNScy4KCjIpCVByZXNlbnQgZGlzY2lwbGluZS1zcGVjaWZpYyByZXNlYXJjaCBwYXR0ZXJucyBieSBzdW1tYXJpc2luZyBjb21tb25hbGl0aWVzIGFuZCBkaXNwYXJpdGllcyBiZXR3ZWVuIGRpc2NpcGxpbmVzIChlLmcuLCBkbyBTUnMgb2Ygc3BlY2lmaWMgZW52aXJvbm1lbnRhbCBleHBvc3VyZXMgZG9taW5hdGUgb25lIGRpc2NpcGxpbmUgYW5kIG5vdCBvdGhlcnM/IERvIHNvbWUgZGlzY2lwbGluZXMgZm9jdXMgb24gaW50ZXItZ2VuZXJhdGlvbmFsIGVmZmVjdHMsIGFuZCBhbm90aGVyIG9uIHRyYW5zLWdlbmVyYXRpb25hbCBlZmZlY3RzPykuCgojIyMgUGVyY2VudCBvZiBTUidzIHdpdGhpbiBkaXNjaXBsaW5lcwoKYGBgIHtyfQoKY291bnRfZGlzY2lwbGluZSA8LVJldmlld19pbmZvICU+JSBjb3VudChkaXNjaXBsaW5lX2NvZGUpICU+JSBhcnJhbmdlKGRlc2MobikpIApwZXJjZW50X2Rpc2NpcGxpbmUgPC0gY291bnRfZGlzY2lwbGluZSAlPiUgbXV0YXRlKHBlcmNlbnQgPSAobi9zdW0obikpKjEwMCkKcGVyY2VudF9kaXNjaXBsaW5lJGRpc2NpcGxpbmVfY29kZSA8LSBmYWN0b3IocGVyY2VudF9kaXNjaXBsaW5lJGRpc2NpcGxpbmVfY29kZSwgbGV2ZWwgPSBwZXJjZW50X2Rpc2NpcGxpbmUkZGlzY2lwbGluZV9jb2RlW29yZGVyKHBlcmNlbnRfZGlzY2lwbGluZSRuLCBkZWNyZWFzaW5nID0gRkFMU0UpXSkKCmdncGxvdChwZXJjZW50X2Rpc2NpcGxpbmUsIGFlcyh4ID0gZGlzY2lwbGluZV9jb2RlLCB5ID0gcGVyY2VudCkpICsgCiAgZ2VvbV9jb2woYWVzKGZpbGwgPSAiIiksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgeGxhYigiRGlzY2lwbGluZSIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzkxOTE5MSIpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKCmBgYAoKIyMjIEludGVyLSB2cyB0cmFucy1nZW5lcmF0aW9uYWwgZWZmZWN0cyB3aXRoaW4gYW5kIGJldHdlZW4gZGlzY2lwbGluZXMKCmBgYHtyfQoKTWVyZ2VkX2ludGVyX3ZzX3RyYW5zIDwtIG1lcmdlKEludGVyX3ZzX3RyYW5zX2luZm8sIFJldmlld19pbmZvKQoKY291bnRfaW50ZXJfdnNfdHJhbnMgPC0gTWVyZ2VkX2ludGVyX3ZzX3RyYW5zICU+JSBjb3VudChpbnRlcl92c190cmFuc19jb2RlLCBieSA9IGRpc2NpcGxpbmVfY29kZSApICU+JSBhcnJhbmdlKGRlc2MobikpCnBlcmNlbnRfaW50ZXJfdnNfdHJhbnMgPC0gY291bnRfaW50ZXJfdnNfdHJhbnMgJT4lIG11dGF0ZShwZXJjZW50ID0gKG4vc3VtKG4pKSoxMDApCgpwZXJjZW50X2ludGVyX3ZzX3RyYW5zIDwtcGVyY2VudF9pbnRlcl92c190cmFucyAlPiUKICByZW5hbWUoCiAgICBkaXNjaXBsaW5lX2NvZGUgPSBieQogICkKCmdncGxvdChwZXJjZW50X2ludGVyX3ZzX3RyYW5zLCBhZXMoeCA9IGludGVyX3ZzX3RyYW5zX2NvZGUsIHkgPSBwZXJjZW50KSkgKyAKICBnZW9tX2NvbChhZXMoZmlsbCA9IGRpc2NpcGxpbmVfY29kZSksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMjIFRhYmxlIHNob3dpbmcgdGhlIGNvbnRyb2xsZWQgdmFjYWJ1bGFybHkgdXNlZCBhbmQgYSBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoZSBjb250cm9sbGVkIHZvY2FidWxhcnkgbWVhbnMuIAoKTm90ZSB0aGF0IHRoZSBkZXNjcmlwdGlvbiBvZnRlbiBlcXVhbHMgY29udHJvbGxlZCB2b2NhYiBidXQgdGhpcyBpcyBub3QgYWx3YXlzIHRoZSBjYXNlIGZvciBtb3JlIGNvbXBsaWNhdGVkIGVsZW1lbnRzLgpgYGAge3J9CkludGVyX3ZzX3RyYW5zX2luZm9fdW5pcXVlIDwtIEludGVyX3ZzX3RyYW5zX2NvZGVfaW5mbyAlPiUgCiAgc2VsZWN0KAogIGNvbnRyb2xsZWRfdm9jYWJfaW50ZXJfdnNfdHJhbnMsIGRlc2NyaXB0aW9uCiAgKSAKdW5pcXVlKEludGVyX3ZzX3RyYW5zX2luZm9fdW5pcXVlKQpgYGAKCiMjIyBEZXNjZW5kYW50IGdlbmVyYXRpb25zIHdpdGhpbiBhbmQgYmV0d2VlbiBkaXNjaXBsaW5lcwoKYGBge3J9CgptZXJnZWRfZGVzY2VuZGFudF9nZW5lcmF0IDwtIG1lcmdlKERlc2NlbmRhbnRfZ2VuZXJhdF9pbmZvLCBSZXZpZXdfaW5mbykKCmNvdW50X2Rlc2NlbmRhbnRfZ2VuZXJhdCA8LSBtZXJnZWRfZGVzY2VuZGFudF9nZW5lcmF0ICU+JSBjb3VudChkZXNjZW5kYW50X2dlbmVyYXRfY29kZSwgYnkgPSBkaXNjaXBsaW5lX2NvZGUpICU+JSBhcnJhbmdlKGRlc2MobikpCnBlcmNlbnRfZGVzY2VuZGFudF9nZW5lcmF0IDwtIGNvdW50X2Rlc2NlbmRhbnRfZ2VuZXJhdCAlPiUgbXV0YXRlKHBlcmNlbnQgPSAobi9zdW0obikpKjEwMCkKCnBlcmNlbnRfZGVzY2VuZGFudF9nZW5lcmF0IDwtIHBlcmNlbnRfZGVzY2VuZGFudF9nZW5lcmF0ICU+JSAKICByZW5hbWUgKAogICAgZGlzY2lwbGluZV9jb2RlID0gYnkKICApCgpnZ3Bsb3QocGVyY2VudF9kZXNjZW5kYW50X2dlbmVyYXQsIGFlcyh4ID0gZGVzY2VuZGFudF9nZW5lcmF0X2NvZGUsIHkgPSBwZXJjZW50KSkgKyAKICBnZW9tX2NvbChhZXMoZmlsbCA9IGRpc2NpcGxpbmVfY29kZSksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMgVGVybWlub2xvZ3kgdXNlZCB3aXRoaW4gYW5kIGJldHdlZW4gZGlzY2lwbGluZXMKSS5lLiwgZG9lcyB0aGUgdXNlIG9mIGludGVyLSBhbmQgdHJhbnMtZ2VuZXJhdGlvbmFsIGluaGVyaXRhbmNlIG1hdGNoIG91ciBkZWZpbml0aW9ucyAoc2VlIEZpZy4gMSkKCmBgYCB7cn0KCmNvdW50X3Rlcm1pbm9sb2d5IDwtIFJldmlld19pbmZvICU+JSBjb3VudCh0ZXJtaW5vbG9neV9jb2RlLCBieSA9IGRpc2NpcGxpbmVfY29kZSkgJT4lIGFycmFuZ2UoZGVzYyhuKSkKcGVyY2VudF90ZXJtaW5vbG9neSA8LSBjb3VudF90ZXJtaW5vbG9neSAlPiUgbXV0YXRlKHBlcmNlbnQgPSAobi9zdW0obikpKjEwMCkKCnBlcmNlbnRfdGVybWlub2xvZ3k8LSBwZXJjZW50X3Rlcm1pbm9sb2d5ICU+JQogIHJlbmFtZSgKICAgIGRpc2NpcGxpbmVfY29kZSA9IGJ5CiAgKQoKZ2dwbG90KHBlcmNlbnRfdGVybWlub2xvZ3ksIGFlcyh4ID0gdGVybWlub2xvZ3lfY29kZSwgeSA9IHBlcmNlbnQpKSArIAogIGdlb21fY29sKGFlcyhmaWxsID0gZGlzY2lwbGluZV9jb2RlKSwgd2lkdGggPSAwLjcpICsgCiAgdGhlbWVfbGlnaHQoKSArCiAgY29vcmRfZmxpcCgpICsgIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMjIFRhYmxlIHNob3dpbmcgdGhlIGNvbnRyb2xsZWQgdmFjYWJ1bGFybHkgdXNlZCBhbmQgYSBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoZSBjb250cm9sbGVkIHZvY2FidWxhcnkgbWVhbnMuIAoKTm90ZSB0aGF0IHRoZSBkZXNjcmlwdGlvbiBvZnRlbiBlcXVhbHMgY29udHJvbGxlZCB2b2NhYiBidXQgdGhpcyBpcyBub3QgYWx3YXlzIHRoZSBjYXNlIGZvciBtb3JlIGNvbXBsaWNhdGVkIGVsZW1lbnRzLgpgYGAge3J9CnRlcm1pbm9sb2d5X2NvZGVfdW5pcXVlIDwtIFRlcm1pbm9sb2d5X2NvZGVfaW5mbyAlPiUgCiAgc2VsZWN0KAogICAgY29udHJvbGxlZF92b2NhYl90ZXJtaW5vbG9neSwgZGVzY3JpcHRpb25fdGVybWlub2xvZ3kKICApCnVuaXF1ZSh0ZXJtaW5vbG9neV9jb2RlX3VuaXF1ZSkKYGBgCgojIyMgVHlwZXMgb2Ygbm9uLWdlbmV0aWMgdHJhbnNtaXNzaW9uIHdpdGhpbiBhbmQgYmV0d2VlbiBkaXNjaXBsaW5lcwpJLmUuLCBhcmUgdGhlIG5vbi1nZW5ldGljIGVmZmVjdHMgY29uZmVycmVkIHRocm91Z2ggdGhlIG1hdHJpbGluZSBvciBwYXRyaWxpbmUgZXRjLgoKYGBge3J9CgpNZXJnZWRfdHJhbnNtaXNzaW9uX2luZm8gPC0gbWVyZ2UoVHJhbnNtaXNzaW9uX2luZm8sIFJldmlld19pbmZvKQoKY291bnRfdHJhbnNtaXNzaW9uIDwtIE1lcmdlZF90cmFuc21pc3Npb25faW5mbyAlPiUgIGNvdW50KHRyYW5zbWlzc2lvbl9jb2RlLCBieSA9IGRpc2NpcGxpbmVfY29kZSkgJT4lIGFycmFuZ2UoZGVzYyhuKSkKcGVyY2VudF90cmFuc21pc3Npb24gPC0gY291bnRfdHJhbnNtaXNzaW9uICU+JSBtdXRhdGUocGVyY2VudCA9IChuL3N1bShuKSkqMTAwKQoKcGVyY2VudF90cmFuc21pc3Npb24gPC1wZXJjZW50X3RyYW5zbWlzc2lvbiAlPiUKICByZW5hbWUoCiAgICBkaXNjaXBsaW5lX2NvZGUgPSBieQogICkKCmdncGxvdChwZXJjZW50X3RyYW5zbWlzc2lvbiwgYWVzKHggPSB0cmFuc21pc3Npb25fY29kZSwgeSA9IHBlcmNlbnQpKSArIAogIGdlb21fY29sKGFlcyhmaWxsID0gZGlzY2lwbGluZV9jb2RlKSwgd2lkdGggPSAwLjcpICsgCiAgdGhlbWVfbGlnaHQoKSArCiAgY29vcmRfZmxpcCgpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiUGVyY2VudCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9IkRpc2NpcGxpbmU6IikpCgpgYGAKCiMjIyMgVGFibGUgc2hvd2luZyB0aGUgY29udHJvbGxlZCB2YWNhYnVsYXJseSB1c2VkIGFuZCBhIGRlc2NyaXB0aW9uIG9mIHdoYXQgdGhlIGNvbnRyb2xsZWQgdm9jYWJ1bGFyeSBtZWFucy4gCgpOb3RlIHRoYXQgdGhlIGRlc2NyaXB0aW9uIG9mdGVuIGVxdWFscyBjb250cm9sbGVkIHZvY2FiIGJ1dCB0aGlzIGlzIG5vdCBhbHdheXMgdGhlIGNhc2UgZm9yIG1vcmUgY29tcGxpY2F0ZWQgZWxlbWVudHMuCmBgYCB7cn0KVHJhbnNtaXNzaW9uX2luZm9fdW5pcXVlIDwtIFRyYW5zbWlzc2lvbl9jb2RlX2luZm8gJT4lIAogIHNlbGVjdCgKICAgIGNvbnRyb2xsZWRfdm9jYWJfdHJhbnNtaXNzaW9uLCBkZXNjcmlwdGlvbgogICkKdW5pcXVlKFRyYW5zbWlzc2lvbl9pbmZvX3VuaXF1ZSkgCgpgYGAKCiMjIyBGMCBlbnZpcm9ubWVudGFsIG1hbmlwdWxhdGlvbnMgd2l0aGluIGFuZCBiZXR3ZWVuIGRpc2NpcGxpbmVzCgpgYGB7cn0KCm1lcmdlZF9GMF9lbnYgPC0gbWVyZ2UoRjBfZW52X2luZm8sIFJldmlld19pbmZvKQoKY291bnRfRjBfZW52PC0gbWVyZ2VkX0YwX2VudiAlPiUgY291bnQoRjBfZW52X2NvZGUsIGJ5ID0gZGlzY2lwbGluZV9jb2RlICkgJT4lIGFycmFuZ2UoZGVzYyhuKSkKcGVyY2VudF9GMF9lbnYgPC0gY291bnRfRjBfZW52ICU+JSBtdXRhdGUocGVyY2VudCA9IChuL3N1bShuKSkqMTAwKQogCnBlcmNlbnRfRjBfZW52IDwtcGVyY2VudF9GMF9lbnYgJT4lCiAgcmVuYW1lKAogICAgZGlzY2lwbGluZV9jb2RlID0gYnkKICApCgpnZ3Bsb3QocGVyY2VudF9GMF9lbnYsIGFlcyh4ID0gRjBfZW52X2NvZGUsIHkgPSBwZXJjZW50KSkgKyAKICBnZW9tX2NvbChhZXMoZmlsbCA9IGRpc2NpcGxpbmVfY29kZSksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMjIFRhYmxlIHNob3dpbmcgdGhlIGNvbnRyb2xsZWQgdmFjYWJ1bGFybHkgdXNlZCBhbmQgYSBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoZSBjb250cm9sbGVkIHZvY2FidWxhcnkgbWVhbnMuIAoKTm90ZSB0aGF0IHRoZSBkZXNjcmlwdGlvbiBvZnRlbiBlcXVhbHMgY29udHJvbGxlZCB2b2NhYiBidXQgdGhpcyBpcyBub3QgYWx3YXlzIHRoZSBjYXNlIGZvciBtb3JlIGNvbXBsaWNhdGVkIGVsZW1lbnRzLgpgYGAge3J9CkYwX2Vudl9pbmZvX3VuaXF1ZSA8LSBGMF9lbnZfY29kZV9pbmZvICU+JSAKICBzZWxlY3QoCiAgICBjb250cm9sbGVkX3ZvY2FiX0YwX2VudiwgZGVzY3JpcHRpb24KICApCnVuaXF1ZShGMF9lbnZfaW5mb191bmlxdWUpCmBgYAoKIyMjIEVudmlyb25tZW50YWwgZWZmZWN0IGRpcmVjdGlvbiB3aXRoaW4gYW5kIGJldHdlZW4gZGlzY2lwbGluZXMKSS5lLiwgYXJlIHRoZSBlZmZlY3RzIG9mIGVudmlyb25tZW50IHByZWRpY3RlZCB0byBoYXZlIG5lZ2F0aXZlLCBwb3NpdGl2ZSwgb3IgbmV1dHJhbCBlZmZlY3RzIG9uIG9mZnNwcmluZyBwaGVub3R5cGUKCmBgYHtyfQoKbWVyZ2VkX2Vudl9lZmYgPC0gbWVyZ2UoRW52X2VmZl9kaWVjdGlvbl9pbmZvLCBSZXZpZXdfaW5mbykKCmNvdW50X2Vudl9lZmYgPC0gbWVyZ2VkX2Vudl9lZmYgJT4lIGNvdW50KGVudl9lZmZfZGlyZWN0aW9uX2NvZGUsIGJ5ID0gZGlzY2lwbGluZV9jb2RlKSAlPiUgYXJyYW5nZShkZXNjKG4pKQpwZXJjZW50X2Vudl9lZmYgPC0gY291bnRfZW52X2VmZiAlPiUgbXV0YXRlKHBlcmNlbnQgPSAobi9zdW0obikpKjEwMCkKCnBlcmNlbnRfZW52X2VmZiA8LXBlcmNlbnRfZW52X2VmZiAlPiUKICByZW5hbWUoCiAgICBkaXNjaXBsaW5lX2NvZGUgPSBieQogICkKCmdncGxvdChwZXJjZW50X2Vudl9lZmYsIGFlcyh4ID0gZW52X2VmZl9kaXJlY3Rpb25fY29kZSwgeSA9IHBlcmNlbnQpKSArIAogIGdlb21fY29sKGFlcyhmaWxsID0gZGlzY2lwbGluZV9jb2RlKSwgd2lkdGggPSAwLjcpICsgCiAgdGhlbWVfbGlnaHQoKSArCiAgY29vcmRfZmxpcCgpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiUGVyY2VudCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9IkRpc2NpcGxpbmU6IikpCgpgYGAKCiMjIyMgVGFibGUgc2hvd2luZyB0aGUgY29udHJvbGxlZCB2YWNhYnVsYXJseSB1c2VkIGFuZCBhIGRlc2NyaXB0aW9uIG9mIHdoYXQgdGhlIGNvbnRyb2xsZWQgdm9jYWJ1bGFyeSBtZWFucy4gCgpOb3RlIHRoYXQgdGhlIGRlc2NyaXB0aW9uIG9mdGVuIGVxdWFscyBjb250cm9sbGVkIHZvY2FiIGJ1dCB0aGlzIGlzIG5vdCBhbHdheXMgdGhlIGNhc2UgZm9yIG1vcmUgY29tcGxpY2F0ZWQgZWxlbWVudHMuCmBgYCB7cn0KRW52X2VmZl9kaXJlY3Rpb25faW5mb191bmlxdWUgPC0gRW52X2VmZl9kaXJlY3Rpb25fY29kZV9pbmZvICU+JSAKICBzZWxlY3QoCiAgICBjb250cm9sbGVkX3ZvY2FiX2Vudl9lZmZfZGlyZWN0aW9uLCBkZXNjcmlwdGlvbgogICkKdW5pcXVlKEVudl9lZmZfZGlyZWN0aW9uX2luZm9fdW5pcXVlKSAKYGBgCgojIyMgRjAgZW52aXJvbm1lbnRhbCBleHBvc3VyZSB0aW1pbmcgd2l0aGluIGFuZCBiZXR3ZWVuIGRpc2NpcGxpbmVzCioqTm90ZToqKiBXZSBleGNsdWRlZCBTUnMgdGhhdCBzb2xlbHkgZm9jdXNlZCBvbiBlbnZpcm9ubWVudGFsIGV4cG9zdXJlcyB0aGF0IG9jY3VyZWQgd2hlbiB0aGUgRjAgZ2VuZXJhdGlvbiB3YXMgYSBmZXR1cyAoaS5lLiwgcHJlLW5hdGFsKS4gSG93ZXZlciwgIHNvbWUgYnJvYWRlciBTUnMgKGkuZS4sIGVjbyBldm8gU1JzKSBpbmNsdWRlZCBwcmltYXJ5IHN0dWRpZXMgd2hlcmUgdGhlIEYwIGdlbmVyYXRpb24gd2FzIGV4cG9zZWQgcHJlLW5hdGFsbHkuIFRoaXMgd2FzIHRoZXJlZm9yZSBjb2RlZCBpbiBvdXIgZGF0YS4gCgpgYGB7cn0KCm1lcmdlZF9leHBvc3VyZV90aW1pbmcgPC0gbWVyZ2UoRXhwb3N1cmVfdGltaW5nX2luZm8sIFJldmlld19pbmZvKQoKY291bnRfZXhwb3N1cmVfdGltaW5nIDwtIG1lcmdlZF9leHBvc3VyZV90aW1pbmcgJT4lIGNvdW50KGV4cG9zdXJlX3RpbWluZ19jb2RlLCBieSA9IGRpc2NpcGxpbmVfY29kZSkgJT4lIGFycmFuZ2UoZGVzYyhuKSkKcGVyY2VudF9leHBvc3VyZV90aW1pbmcgPC0gY291bnRfZXhwb3N1cmVfdGltaW5nICU+JSBtdXRhdGUocGVyY2VudCA9IChuL3N1bShuKSkqMTAwKQoKcGVyY2VudF9leHBvc3VyZV90aW1pbmcgPC1wZXJjZW50X2V4cG9zdXJlX3RpbWluZyAlPiUKICByZW5hbWUgKAogICAgZGlzY2lwbGluZV9jb2RlID0gYnkKICApCgpnZ3Bsb3QocGVyY2VudF9leHBvc3VyZV90aW1pbmcsIGFlcyh4ID0gZXhwb3N1cmVfdGltaW5nX2NvZGUsIHkgPSBwZXJjZW50KSkgKyAKICBnZW9tX2NvbChhZXMoZmlsbCA9IGRpc2NpcGxpbmVfY29kZSksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMjIFRhYmxlIHNob3dpbmcgdGhlIGNvbnRyb2xsZWQgdmFjYWJ1bGFybHkgdXNlZCwgYW5kIGEgZGVzY3JpcHRpb24gb2Ygd2hhdCB0aGUgY29udHJvbGxlZCB2b2NhYnVsYXJ5IG1lYW5zLiAKCk5vdGUgdGhhdCB0aGUgZGVzY3JpcHRpb24gb2Z0ZW4gZXF1YWxzIGNvbnRyb2xsZWQgdm9jYWIgYnV0IHRoaXMgaXMgbm90IGFsd2F5cyB0aGUgY2FzZSBmb3IgbW9yZSBjb21wbGljYXRlZCBlbGVtZW50cy4KYGBgIHtyfQpFeHBvc3VyZV90aW1pbmdfaW5mb191bmlxdWU8LSBFeHBvc3VyZV90aW1pbmdfY29kZV9pbmZvICU+JSAKICBzZWxlY3QoCiAgICBjb250cm9sbGVkX3ZvY2FiX2V4cG9zdXJlX3RpbWluZywgZGVzY3JpcHRpb24KICApCnVuaXF1ZShFeHBvc3VyZV90aW1pbmdfaW5mb191bmlxdWUpIApgYGAKCiMjIyBEZXNjZW5kYW50IHRyYWl0cyB3aXRoaW4gYW5kIGJldHdlZW4gZGlzY2lwbGluZXMgCgpgYGB7cn0KCm1lcmdlZF9kZXNjZW5kYW50X3RyYWl0IDwtIG1lcmdlKERlc2NlbmRhbnRfdHJhaXRfaW5mbywgUmV2aWV3X2luZm8pCgpjb3VudF9kZXNjZW5kYW50X3RyYWl0IDwtIG1lcmdlZF9kZXNjZW5kYW50X3RyYWl0ICU+JSBjb3VudChkZXNjZW5kYW50X3RyYWl0X2NvZGUsIGJ5ID0gZGlzY2lwbGluZV9jb2RlKSAlPiUgYXJyYW5nZShkZXNjKG4pKQpwZXJjZW50X2Rlc2NlbmRhbnRfdHJhaXQgPC0gY291bnRfZGVzY2VuZGFudF90cmFpdCAlPiUgbXV0YXRlKHBlcmNlbnQgPSAobi9zdW0obikpKjEwMCkKCnBlcmNlbnRfZGVzY2VuZGFudF90cmFpdCA8LSBwZXJjZW50X2Rlc2NlbmRhbnRfdHJhaXQgJT4lCiAgcmVuYW1lKAogICAgZGlzY2lwbGluZV9jb2RlID0gYnkKICApCgpnZ3Bsb3QocGVyY2VudF9kZXNjZW5kYW50X3RyYWl0LCBhZXMoeCA9IGRlc2NlbmRhbnRfdHJhaXRfY29kZSwgeSA9IHBlcmNlbnQpKSArIAogIGdlb21fY29sKGFlcyhmaWxsID0gZGlzY2lwbGluZV9jb2RlKSwgd2lkdGggPSAwLjcpICsgCiAgdGhlbWVfbGlnaHQoKSArIAogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMjIFRhYmxlIHNob3dpbmcgdGhlIGNvbnRyb2xsZWQgdmFjYWJ1bGFybHkgdXNlZCBhbmQgYSBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoZSBjb250cm9sbGVkIHZvY2FidWxhcnkgbWVhbnMuIAoKTm90ZSB0aGF0IHRoZSBkZXNjcmlwdGlvbiBvZnRlbiBlcXVhbHMgY29udHJvbGxlZCB2b2NhYiBidXQgdGhpcyBpcyBub3QgYWx3YXlzIHRoZSBjYXNlIGZvciBtb3JlIGNvbXBsaWNhdGVkIGVsZW1lbnRzLgpgYGAge3J9CkRlc2NlbmRhbnRfdHJhaXRfaW5mb191bmlxdWU8LURlc2NlbmRhbnRfdHJhaXRfY29kZV9pbmZvICU+JSAKICBzZWxlY3QoCiAgICAgY29udHJvbGxlZF92b2NhYl9kZXNjZW5kYW50X3RyYWl0LGRlc2NyaXB0aW9uCiAgKQp1bmlxdWUoRGVzY2VuZGFudF90cmFpdF9pbmZvX3VuaXF1ZSkgCmBgYAoKIyMjIERlc2NlbmRhbnQgc2V4IHdpdGhpbiBhbmQgYmV0d2VlbiBkaXNjaXBsaW5lcwoKYGBge3J9CgptZXJnZWRfZGVzY2VuZGFudF9zZXggPC0gbWVyZ2UoRGVzY2VuZGFudF9zZXhfaW5mbywgUmV2aWV3X2luZm8pCgpjb3VudF9kZXNjZW5kYW50X3NleCA8LSBtZXJnZWRfZGVzY2VuZGFudF9zZXggJT4lIGNvdW50KGRlc2NlbmRhbnRfc2V4X2NvZGUsIGJ5ID0gZGlzY2lwbGluZV9jb2RlKSAlPiUgYXJyYW5nZShkZXNjKG4pKQpwZXJjZW50X2Rlc2NlbmRhbnRfc2V4IDwtIGNvdW50X2Rlc2NlbmRhbnRfc2V4ICAlPiUgbXV0YXRlKHBlcmNlbnQgPSAobi9zdW0obikpKjEwMCkKCnBlcmNlbnRfZGVzY2VuZGFudF9zZXggPC0gcGVyY2VudF9kZXNjZW5kYW50X3NleCAlPiUKICByZW5hbWUoCiAgICBkaXNjaXBsaW5lX2NvZGUgPSBieQogICAgICAgICAgICkKCmdncGxvdChwZXJjZW50X2Rlc2NlbmRhbnRfc2V4LCBhZXMoeCA9IGRlc2NlbmRhbnRfc2V4X2NvZGUsIHkgPSBwZXJjZW50KSkgKyAKICBnZW9tX2NvbChhZXMoZmlsbCA9IGRpc2NpcGxpbmVfY29kZSksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMjIFRhYmxlIHNob3dpbmcgdGhlIGNvbnRyb2xsZWQgdmFjYWJ1bGFybHkgdXNlZCBhbmQgYSBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoZSBjb250cm9sbGVkIHZvY2FidWxhcnkgbWVhbnMuIAoKTm90ZSB0aGF0IHRoZSBkZXNjcmlwdGlvbiBvZnRlbiBlcXVhbHMgY29udHJvbGxlZCB2b2NhYiBidXQgdGhpcyBpcyBub3QgYWx3YXlzIHRoZSBjYXNlIGZvciBtb3JlIGNvbXBsaWNhdGVkIGVsZW1lbnRzLgpgYGAge3J9CkRlc2NlbmRhbnRfc2V4X2luZm9fdW5pcXVlPC0gRGVzY2VuZGFudF9zZXhfY29kZV9pbmZvJT4lIAogIHNlbGVjdCgKICAgIGNvbnRyb2xsZWRfdm9jYWJfZGVzY2VuZGFudF9zZXgsIGRlc2NyaXB0aW9uCiAgKQp1bmlxdWUoRGVzY2VuZGFudF9zZXhfaW5mb191bmlxdWUpCmBgYAoKIyMjIERlc2NlbmRhbnQgYWdlIHdpdGhpbiBhbmQgYmV0d2VlbiBkaXNjaXBsaW5lcwoqKk5vdGU6KiogV2UgZXhjbHVkZWQgU1JzIHRoYXQgc29sZWx5IGZvY3VzZWQgb24gZmV0YWwgdHJhaXRzIGluIGRlc2NlbmRhbnRzLiBIb3dldmVyLCBzb21lIGJyb2FkZXIgU1JzIGluY2x1ZGVkIHByaW1hcnkgc3R1ZGllcyB0aGF0IG1lYXJ1cmVkIGZldGFsIHRyYWl0cy4gVGhpcyB3YXMgdGhlcmVmb3JlIGNvZWRlZCBpbiBvdXIgZGF0YS4gCgpgYGB7cn0KCm1lcmdlZF9kZXNjZW5kYW50X2FnZSA8LSBtZXJnZShEZXNjZW5kYW50X2FnZV9pbmZvLCBSZXZpZXdfaW5mbykKCmNvdW50X2Rlc2NlbmRhbnRfYWdlIDwtIG1lcmdlZF9kZXNjZW5kYW50X2FnZSAlPiUgY291bnQoZGVzY2VuZGFudF9hZ2VfY29kZSwgYnkgPSBkaXNjaXBsaW5lX2NvZGUpICU+JSBhcnJhbmdlKGRlc2MobikpCnBlcmNlbnRfZGVzY2VuZGFudF9hZ2UgPC0gY291bnRfZGVzY2VuZGFudF9hZ2UgJT4lIG11dGF0ZShwZXJjZW50ID0gKG4vc3VtKG4pKSoxMDApCgpwZXJjZW50X2Rlc2NlbmRhbnRfYWdlIDwtIHBlcmNlbnRfZGVzY2VuZGFudF9hZ2UgJT4lCiAgcmVuYW1lKAogICAgZGlzY2lwbGluZV9jb2RlID0gYnkKICApCgpnZ3Bsb3QocGVyY2VudF9kZXNjZW5kYW50X2FnZSwgYWVzKHggPSBkZXNjZW5kYW50X2FnZV9jb2RlLCB5ID0gcGVyY2VudCkpICsgCiAgZ2VvbV9jb2woYWVzKGZpbGwgPSBkaXNjaXBsaW5lX2NvZGUpLCB3aWR0aCA9IDAuNykgKyAKICB0aGVtZV9saWdodCgpICsKICBjb29yZF9mbGlwKCkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJQZXJjZW50IikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSArIAogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT0iRGlzY2lwbGluZToiKSkKCmBgYAoKIyMjIyBUYWJsZSBzaG93aW5nIHRoZSBjb250cm9sbGVkIHZhY2FidWxhcmx5IHVzZWQgYW5kIGEgZGVzY3JpcHRpb24gb2Ygd2hhdCB0aGUgY29udHJvbGxlZCB2b2NhYnVsYXJ5IG1lYW5zLiAKCk5vdGUgdGhhdCB0aGUgZGVzY3JpcHRpb24gb2Z0ZW4gZXF1YWxzIGNvbnRyb2xsZWQgdm9jYWIgYnV0IHRoaXMgaXMgbm90IGFsd2F5cyB0aGUgY2FzZSBmb3IgbW9yZSBjb21wbGljYXRlZCBlbGVtZW50cy4KYGBgIHtyfQpEZXNjZW5kYW50X2FnZV9pbmZvX3VuaXF1ZTwtIERlc2NlbmRhbnRfYWdlX2NvZGVfaW5mbyAlPiUgCiAgc2VsZWN0KAogICAgY29udHJvbGxlZF92b2NhYl9kZXNjZW5kYW50X2FnZSwgZGVzY3JpcHRpb24KICApCnVuaXF1ZShEZXNjZW5kYW50X2FnZV9pbmZvX3VuaXF1ZSkgCmBgYAoKIyMjIEhpZ2hlciB0YXhvbm9ubWljIGdyb3VwcyB3aXRoaW4gYW5kIGJldHdlZW4gZGlzY2lwbGluZXMgCgpgYGAge3J9CgpNZXJnZWRfaGlnaGVyX3RheG9uIDwtIG1lcmdlKEhpZ2hlcl90YXhvbl9pbmZvLCBSZXZpZXdfaW5mbykKCmNvdW50X2hpZ2hlcl90YXhvbiA8LSBNZXJnZWRfaGlnaGVyX3RheG9uICU+JSBjb3VudCh0YXhvbl9jb2RlLCBieSA9IGRpc2NpcGxpbmVfY29kZSkgJT4lIGFycmFuZ2UoZGVzYyhuKSkKcGVyY2VudF9oaWdoZXJfdGF4b24gPC0gY291bnRfaGlnaGVyX3RheG9uICU+JSBtdXRhdGUocGVyY2VudCA9IChuL3N1bShuKSkqMTAwKQoKcGVyY2VudF9oaWdoZXJfdGF4b248LXBlcmNlbnRfaGlnaGVyX3RheG9uICU+JQogIHJlbmFtZSgKICAgIGRpc2NpcGxpbmVfY29kZSA9IGJ5CiAgKQoKZ2dwbG90KHBlcmNlbnRfaGlnaGVyX3RheG9uLCBhZXMoeCA9IHRheG9uX2NvZGUsIHkgPSBwZXJjZW50KSkgKyAKICBnZW9tX2NvbChhZXMoZmlsbCA9IGRpc2NpcGxpbmVfY29kZSksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJEaXNjaXBsaW5lOiIpKQoKYGBgCgojIyMjIFRhYmxlIHNob3dpbmcgdGhlIGNvbnRyb2xsZWQgdmFjYWJ1bGFybHkgdXNlZCBhbmQgYSBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoZSBjb250cm9sbGVkIHZvY2FidWxhcnkgbWVhbnMuIAoKTm90ZSB0aGF0IHRoZSBkZXNjcmlwdGlvbiBvZnRlbiBlcXVhbHMgY29udHJvbGxlZCB2b2NhYiBidXQgdGhpcyBpcyBub3QgYWx3YXlzIHRoZSBjYXNlIGZvciBtb3JlIGNvbXBsaWNhdGVkIGVsZW1lbnRzLgpgYGAge3J9CkhpZ2hlcl90YXhvbl9pbmZvX3VuaXF1ZTwtIFRheG9uX2NvZGVfaW5mbyAlPiUgCiAgc2VsZWN0KAogICAgY29udHJvbGxlZF92b2NhYl90YXhvbiwgZGVzY3JpcHRpb24KICApCnVuaXF1ZShIaWdoZXJfdGF4b25faW5mb191bmlxdWUpCmBgYAoKIyMjIERlc2NlbmRlbnQgZ2VuZXJhdGlvbiB2cyB0ZXJtaW5vbG9neSB1c2UgYWNyb3NzIGRpc2NpcGxpbmVzCkRvZXMgdGhlIHRlcm1pbm9sb2d5IHVzZWQgKGkuZS4sIGludGVyLSB2cyB0cmFucy1nZW5lcmF0aW9uYWwpIG1hdGNoIG91ciBkZWZpbml0aW9uIChiYXNlZCBvbiBnZW5lcmF0aW9uLCBzZXggYW5kIHRheGEpIHdpdGhpbiB0aGUgIGRlc2NlbmRhbnQgZ2VuZXJhdGlvbnMgZXhhbWluZWQKCmBgYCB7cn0KCmdlbmVyYXRfdGVybWlub2xvZ3kgPC0gbWVyZ2UoRGVzY2VuZGFudF9nZW5lcmF0X2luZm8sIFJldmlld19pbmZvKQogIApjb3VudF9nZW5lcmF0X3Rlcm1pbm9sb2d5IDwtIGdlbmVyYXRfdGVybWlub2xvZ3kgJT4lIGNvdW50KGRlc2NlbmRhbnRfZ2VuZXJhdF9jb2RlLCBieSA9IHRlcm1pbm9sb2d5X2NvZGUpICU+JSBhcnJhbmdlKGRlc2MobikpCnBlcmNlbnRfZ2VuZXJhdF90ZXJtaW5vbG9neSA8LSBjb3VudF9nZW5lcmF0X3Rlcm1pbm9sb2d5ICU+JSBtdXRhdGUocGVyY2VudCA9IChuL3N1bShuKSkqMTAwKQoKcGVyY2VudF9nZW5lcmF0X3Rlcm1pbm9sb2d5PC1wZXJjZW50X2dlbmVyYXRfdGVybWlub2xvZ3kgJT4lCiAgcmVuYW1lKAogICAgdGVybWlub2xvZ3lfY29kZSA9IGJ5CiAgKQoKZ2dwbG90KHBlcmNlbnRfZ2VuZXJhdF90ZXJtaW5vbG9neSwgYWVzKHggPSBkZXNjZW5kYW50X2dlbmVyYXRfY29kZSwgeSA9IHBlcmNlbnQpKSArIAogIGdlb21fY29sKGFlcyhmaWxsID0gdGVybWlub2xvZ3lfY29kZSksIHdpZHRoID0gMC43KSArIAogIHRoZW1lX2xpZ2h0KCkgKwogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcmNlbnQiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJUZXJtaW5vbG9neToiKSkKYGBgCgojIyMgVGltZSB0cmVuZCBvZiB0aGUgbnVtYmVyIG9mIFNScyBwZXIgeWVhcgoKYGBgIHtyfQoKUHVibGljYXRpb25faW5mbyAlPiUgY291bnQoeWVhcikgJT4lIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBuKSkgKyAKICBnZW9tX2FyZWEoZmlsbCA9ICcjOTE5MTkxJywgYWxwaGEgPSAxKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gJ3NreWJsdWUnLCBzaXplID0gMSkgKyAKICBnZW9tX3BvaW50KHNpemU9MSwgY29sb3IgPSAnYmx1ZScpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIiIsIGxpbWl0cyA9IGMoMjAwNSwgMjAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJBcnRpY2xlIGNvdW50IiwgbGltaXRzID0gYygwLCAxMCkpICsKICBnZ3RpdGxlKCJQdWJsaWNhdGlvbiB5ZWFyIikgKyAKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCmBgYAoKIyMgQWRyZXNzaW5nIG9iamVjdGl2ZSAzIHsudGFic2V0fQoKMykJQ29uZHVjdCBiaWJsaW9tZXRyaWMgYW5hbHlzZXMgb2YgY28tYXV0aG9yIG5ldHdvcmtzIGFuZCBjb21tb24gdGVybWlub2xvZ3kgdXNlIGFjcm9zcyBhbmQgd2l0aGluIGRpc2NpcGxpbmVzLiAKClRoZSBmb2xsb3dpbmcgdmlzdWFsaXNhdGlvbnMgYWxsb3cgdXMgdG8gdmlldyBiaWJsaW9tZXRyaWMgcGF0dGVybnMgZnJvbSBkYXRhIGV4cG9ydGVkIGRpcmVjdGx5IGZyb20gc2NvcHVzLiBXZSBhcmUgYWJsZSB0byB2aWV3IGNvbW1vbiBrZXl3b3JkIHVzZSwgYXV0aG9yIG5ldHdvcmtzLCBhZmZpbGlhdGlvbnMsIGFuZCBjaXRhdGlvbiBwYXR0ZXJucy4gCgojIyMgQXV0aG9yLCBjb3VudHJ5LCBhbmQgY2l0YXRpb24gc3VtbWFyeSBwbG90cwoKYGBgIHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30KcmVzdWx0czEgPC0gYmlibGlvQW5hbHlzaXMoYmliKSAjcnVuIGJhc2ljIHN0YW5kYXJkIGRlc2NyaXB0aXZlIGFuYWx5c2lzIG9mIHRoZSBkYXRhc2V0IChkYXRhIGZyYW1lKQpzdW1tYXJ5KHJlc3VsdHMxLCBrID0gNywgcGF1c2UgPSBGLCB3aWR0aCA9IDEzMCkgI3Byb2R1Y2VzIGEgc2VxdWVuY2Ugb2Ygc3RhbmRhcmQgc3VtbWFyeSB0YWJsZXMgZGlzcGxheWVkIGluIHRoZSBjb25zb2xlCnBsb3QocmVzdWx0czEsIGsgPSA3LCBwYXVzZSA9IEYpCmBgYAoKIyMjIEtleXdvcmQgbWF0cml4IHBsb3QKCmBgYCB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9Ck5ldE1hdHJpeF9rZXl3b3JkcyA8LSBiaWJsaW9OZXR3b3JrKGJpYiwgYW5hbHlzaXMgPSAiY28tb2NjdXJyZW5jZXMiLCBuZXR3b3JrID0gImtleXdvcmRzIiwgc2VwID0gIjsiKQpOZXRNYXRyaXhfa2V5d29yZHNfcGxvdCA8LSBuZXR3b3JrUGxvdChOZXRNYXRyaXhfa2V5d29yZHMsIG5vcm1hbGl6ZT0iYXNzb2NpYXRpb24iLCBuID0gMTAsIFRpdGxlID0gIktleXdvcmQgY28tb2NjdXJyZW5jZXMiLCB0eXBlID0gImZydWNodGVybWFuIiwgc2l6ZS5jZXggPSBUUlVFLCBzaXplID0gMzAsIHJlbW92ZS5tdWx0aXBsZSA9IEYsIGVkZ2VzaXplID0gMTAsIGxhYmVsc2l6ZSA9IDMsIGxhYmVsLmNleCA9IFRSVUUsZWRnZXMubWluID0gMiwgY2x1c3RlciA9ICJlZGdlX2JldHdlZW5uZXNzIikKYGBgCgojIyMgVGhlbWF0aWMgbWFwCgpgYGAge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQptYXBfdGhlbWF0aWMgPC0gdGhlbWF0aWNNYXAoYmliLCBmaWVsZCA9ICJJRCIsIG4gPSAxMDAwLCBtaW5mcmVxID0gNSwgc3RlbW1pbmcgPSBGQUxTRSwgc2l6ZSA9IDAuNSwgbi5sYWJlbHMgPSAxLCByZXBlbCA9IFRSVUUpCnBsb3QobWFwX3RoZW1hdGljJG1hcCkKYGBgCgojIyMgQXV0aG9yIGNvbGxhYm9yYXRpb24gbmV0d29yawoKYGBgIHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KTmV0TWF0cml4X2F1dGhvcnMgPC0gYmlibGlvTmV0d29yayhiaWIsIGFuYWx5c2lzID0gImNvbGxhYm9yYXRpb24iLCAgbmV0d29yayA9ICJhdXRob3JzIiwgc2VwID0gIjsiKQpOZXRNYXRyaXhfYXV0aG9yc19wbG90IDwtIG5ldHdvcmtQbG90KE5ldE1hdHJpeF9hdXRob3JzLCAgbiA9IDIwLCBUaXRsZSA9ICJBdXRob3IgY29sbGFib3JhdGlvbiIsIHR5cGUgPSAiYXV0byIsIHNpemUgPSAxNSwgc2l6ZS5jZXggPSBUUlVFLCBlZGdlc2l6ZSA9IDEwLCBsYWJlbHNpemUgPSAxKSAKYGBgCgojIyMgQ291bnRyeSBjb2xsYWJvcmF0aW9uIG5ldHdvcmsKCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KYmliX3NjbzIgPC0gbWV0YVRhZ0V4dHJhY3Rpb24oYmliLCBGaWVsZCA9ICJBVV9DTyIsIHNlcCA9ICI7IikgI3dlIG5lZWQgdG8gZXh0cmFjdCBjb3VudHJpZXMgZnJvbSB0aGUgYWZmaWxpYXRpb25zIGZpcnN0CiNiaWJfc2NvMiRBVV9DT1sxOjEwXQpOZXRNYXRyaXhfY291bnRyeSA8LSBiaWJsaW9OZXR3b3JrKGJpYl9zY28yLCBhbmFseXNpcyA9ICJjb2xsYWJvcmF0aW9uIiwgbmV0d29yayA9ICJjb3VudHJpZXMiLCBzZXAgPSAiOyIpCk5ldE1hdHJpeF9jb3VudHJ5X3Bsb3QgPC0gIG5ldHdvcmtQbG90KE5ldE1hdHJpeF9jb3VudHJ5LCBuID0gNTAsIFRpdGxlID0gIkNvdW50cnkgY29sbGFib3JhdGlvbiIsIHR5cGUgPSAiYXV0byIsIHNpemU9VFJVRSwgcmVtb3ZlLm11bHRpcGxlPUZBTFNFLCBsYWJlbHNpemU9MS41KQpgYGAKCiMjIEFkZHJlc3Npbmcgb2JqZWN0aXZlIDQKCjQpCUNvbmR1Y3QgYSBjcml0aWNhbCBhcHByYWlzYWwgb2YgdGhlIFNSIGxpdGVyYXR1cmUgdG8gYXNzZXNzIHRoZSByaWdvdXIsIHRyYW5zcGFyZW5jeSwgYW5kIHJpc2sgb2YgYmlhcy4gCgpUaGUgZm9sbG93aW5nIHZpc3VhbGlzYXRpb25zIGFsbG93IHVzIHRvIHNlZSB0aGUgYXZlcmFnZSBzY29yZXMgYWNyb3NzIGVhY2ggQ0VFU0FUIHF1ZXN0aW9ucyBhcyB3ZWxsIGFzIGhvdyBlYWNoIGluZGl2aWR1YWwgU1Igc2NvcmVkIGZvciBlYWNoIENFRVNBVCBxdWVzdGlvbnMuIFRoaXMgd2lsbCBhbGxvdyB1cyB0byBhc3Nlc3MgdGhlIHF1YWxpdHkgYW5kIFJpc2sgb2YgQmlhcyBvZiB0aGUgU1IgbGl0ZXJhdHVyZS4gCgoqKk5vdGU6KiogQ0VFU0FUIHF1ZXN0aW9ucyBhbmQgc2NvcmluZyBjcml0ZXJpYSBjYW4gYmUgZm91bmQgaW4gQXBwZW5kaXhfUzMgb24gdGhlIG9wZW4gU2NpZW5jZSBGcmFtZXdvcmsgaHR0cHM6Ly9vc2YuaW8vZGV0dmsvLgoKIyMjIEJsaW5kaW5nIHBhcGVyIElEIGFuZCB3cmFuZ2xpbmcgZGF0YSBpbnRvIGxvbmcgZm9ybWF0CgpQYXBlciBJRCB3YXMgYmxpbmRlZCBmb3IgdGhlIHBpbG90IGJ1dCB3aWxsIG5vdCBiZSBibGluZGVkIGZvciB0aGUgZnVsbCBzdHVkeQoKYGBge3J9CiNibGluZGluZyBhdXRob3JzCkFzc2Vzc21lbnQkaWQgPC0gcGFzdGUoIklEIiwgYygxOmxlbmd0aChBc3Nlc3NtZW50JGlkKSksIHNlcCA9ICIiKQojc2hvcnRlbmluZyBjb2x1bW4gbmFtZXMKbmFtZXMoQXNzZXNzbWVudCkgPC0gZ3N1YigiQ0VFU0FUXyIsICIiLCBuYW1lcyhBc3Nlc3NtZW50KSwgZml4ZWQgPSBUUlVFKQojc2VsZWN0aW5nIG9ubHkgdGhlIGNvbHVtbnMgd2l0aCBzY29yZXMKI3NlbGVjdGluZyBvbmx5IHRoZSBjb2x1bW5zIHdpdGggc2NvcmVzCkFzc2Vzc21lbnRfcmVkdWNlZCA8LSBzZWxlY3QoQXNzZXNzbWVudCwgYygiaWQiLCAhZW5kc193aXRoKCJfY29tbWVudCIpKSkKI3dyYW5nbGluZyBkYXRhIGludG8gbG9uZyBmb3JtYXQKY2Vlc2F0X2xvbmcgPC0gZ2F0aGVyKEFzc2Vzc21lbnRfcmVkdWNlZCwgcXVlc3Rpb24sIHNjb3JlLCBRMS4xOlE4LjEsIGZhY3Rvcl9rZXk9VFJVRSkKYGBgCgojIyMgQ0VFU0FUIHNjb3JlIHN1bW1hcnkgYWNyb3NzIFNScwpUaGlzIHBsb3Qgc2hvd3MgdGhlIGF2ZXJhZ2UgQ0VFU0FUIHNjb3JlIHBlciBxdWVzdGlvbi4gCkNFRVNBVCBxdWVzdGlvbnMgYW5kIHNjb3JpbmcgY3JpdGVyaWEgY2FuIGJlIGZvdW5kIGluIEFwcGVuZGl4X1MzIG9uIHRoZSBvcGVuIFNjaWVuY2UgRnJhbWV3b3JrIGh0dHBzOi8vb3NmLmlvL2RldHZrLy4KCmBgYCB7cn0KI2NhbGN1bGF0aW5nIHRoZSAlIG9mIHNjb3JlcyB3aXRoaW4gZWFjaCBxdWVzdGlvbnMgCmNvdW50X2NlZXNhdF9zY29yZSA8LSBjZWVzYXRfbG9uZyAlPiUgY291bnQoc2NvcmUsIGJ5ID0gcXVlc3Rpb24pIApwZXJjZW50X2NlZXNhdF9zY29yZSA8LSBjb3VudF9jZWVzYXRfc2NvcmUgJT4lIG11dGF0ZShwZXJjZW50ID0gKG4vc3VtKG4pKSoxMDApCnBlcmNlbnRfY2Vlc2F0X3Njb3JlIDwtIHBlcmNlbnRfY2Vlc2F0X3Njb3JlICU+JQogIHJlbmFtZSgKICAgIHF1ZXN0aW9uID0gYnkKICApCnBlcmNlbnRfY2Vlc2F0X3Njb3JlJHF1ZXN0aW9uIDwtIGFzLmZhY3RvcihwZXJjZW50X2NlZXNhdF9zY29yZSRxdWVzdGlvbikKcGVyY2VudF9jZWVzYXRfc2NvcmUkcXVlc3Rpb24gPC0gZmFjdG9yKHBlcmNlbnRfY2Vlc2F0X3Njb3JlJHF1ZXN0aW9uLCBsZXZlbHMocGVyY2VudF9jZWVzYXRfc2NvcmUkcXVlc3Rpb24pW2xlbmd0aChwZXJjZW50X2NlZXNhdF9zY29yZSRxdWVzdGlvbik6MV0pICNyZXZlcnNlIHRoZSBvcmRlciBvZiBxdWVzdGlvbnMKcGVyY2VudF9jZWVzYXRfc2NvcmUkc2NvcmUgPC0gYXMuZmFjdG9yKHBlcmNlbnRfY2Vlc2F0X3Njb3JlJHNjb3JlKQpwZXJjZW50X2NlZXNhdF9zY29yZSRzY29yZSA8LSBmYWN0b3IocGVyY2VudF9jZWVzYXRfc2NvcmUkc2NvcmUsIGxldmVscyhwZXJjZW50X2NlZXNhdF9zY29yZSRzY29yZSlbYygyLDMsMSw0KV0pICNzZXQgdGhlIG9yZGVyIG9mIGxldmVscyBmb3IgYXNzZXNzbWVudCBzY29yZXM6CnN1bW1hcnlwbG90IDwtIGdncGxvdChkYXRhID0gcGVyY2VudF9jZWVzYXRfc2NvcmUsIHggPSBxdWVzdGlvbiwgeSA9IHBlcmNlbnQpICsKICBnZW9tX2NvbChtYXBwaW5nID0gYWVzKHggPSBxdWVzdGlvbiwgeSA9IHBlcmNlbnQsIGZpbGwgPSBzY29yZSksIHdpZHRoID0gMC43LAogICAgICAgICAgIHBvc2l0aW9uID0gImZpbGwiLCBjb2xvciA9ICJibGFjayIpICsKICBjb29yZF9mbGlwKHlsaW0gPSBjKDAsIDEpKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygieWVsbG93IiwiZ3JlZW4iLCAib3JhbmdlIiwicmVkIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSxwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgeWxhYigiUGVyY2VudCIpICsgeGxhYigiQ0VFU0FUIHF1ZXN0aW9uIikgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT0iU2NvcmU6IikpIApzdW1tYXJ5cGxvdApgYGAKCiMjIyBJbmRpdmlkdWFsIENFRVNBVCBTY29yZXMgClRoaXMgcGxvdCBzaG93cyB0aGUgQ0VFU0FUIHNjb3JlIHBlciBTUi4KQ0VFU0FUIHF1ZXN0aW9ucyBhbmQgc2NvcmluZyBjcml0ZXJpYSBjYW4gYmUgZm91bmQgaW4gQXBwZW5kaXhfUzMgb24gdGhlIG9wZW4gU2NpZW5jZSBGcmFtZXdvcmsgaHR0cHM6Ly9vc2YuaW8vZGV0dmsvLgoKYGBgIHtyfQpzY29yZXNwbG90IDwtIGdncGxvdChkYXRhID0gY2Vlc2F0X2xvbmcsIGFlcyh5ID0gaWQsIHggPSBxdWVzdGlvbikpICsKICBnZW9tX3RpbGUoY29sb3I9ImJsYWNrIiwgZmlsbD0id2hpdGUiLCBzaXplID0gMC44KSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBhcy5mYWN0b3Ioc2NvcmUpKSwgc2l6ZSA9IDUpICsKICBzY2FsZV94X2Rpc2NyZXRlKHBvc2l0aW9uID0gInRvcCIpICsKICBndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIm9yYW5nZSIsInllbGxvdyIsImdyZWVuIiwicmVkIiApLCBuYW1lID0gIlNjb3JlOiIpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QobGluZXR5cGUgPSAic29saWQiLCBjb2xvdXIgPSAiZ3JleSIpLAogICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC43NSwgImNtIiksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3Q9MCksCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMSwxLDEsMCksICJjbSIpCiAgKSArCiAgeWxhYigiU3R1ZHkgSUQiKSArIAogIHhsYWIoIkNFRVNBVCBxdWVzdGlvbiIpIApzY29yZXNwbG90CmBgYA==